package n7.restaurant.java.Entity;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;

import n7.restaurant.java.Enum.Etat_Plat;
import n7.restaurant.java.Enum.Etat_Serveur;
import n7.restaurant.java.Enum.TypePlat;
import n7.restaurant.java.Enum.Role;
import n7.restaurant.java.Swing.Swing;

public class Specialiste extends Agent {

	public static ArrayList<Specialiste> specialistes = new ArrayList<Specialiste>();
	private TypePlat capacite;
	private String toString;

	public String getToString() {
		return toString;
	}

	public void setToString(String toString) {
		this.toString = toString;
	}

	private Vector<Plat> taches = new Vector<Plat>();

	public Specialiste() {
		super();
	}

	@Override
	public String toString() {
		String returnString = this.getId() + ": \n";
		if (!this.getEtat_mentaux().isEmpty()) {
			for (int i = 0;i<this.getEtat_mentaux().size(); i++) {
				Etat_Mental em = this.getEtat_mentaux().get(i);
				returnString += em.toString() + "\n";
			}
		}
		return returnString;
	}

	public Specialiste(TypePlat capacite) {
		super();
		this.capacite = capacite;
	}

	public Specialiste(String id, Role role,
			ArrayList<Etat_Mental> etat_mentaux, Position position) {
		super(id, role, etat_mentaux, position);
	}

	public TypePlat getCapacite() {
		return capacite;
	}

	public void setCapacite(TypePlat capacite) {
		this.capacite = capacite;
	}

	@Override
	/**
	 * le methode du thread
	 * */
	public void run() {
		while (true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// nouvel tache arrive?
			if (hasTacheArrive()) {
				// l'etat mental -> taches
				// supprimer l'etat mental
				analyserTache();
				// System.out.println(this);
			} else if (taches.size() != 0) {
				// il a des tache a faire
				// ingredient est pret?
				// boucle
				for (Iterator<Plat> i = this.taches.iterator(); i.hasNext();) {
					Plat p = i.next();
					/*
					 * System.out.println(p.getNom());
					 * System.out.println(p.getEtat());
					 */
					// ingredient sont prets
					if (p.getEtat() == Etat_Plat.ready_to_do) {
						// faire le plat -> boucle
						try {
							Thread.sleep(p.getDuree());
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						// done, modifier l'etat
						p.setEtat(Etat_Plat.done);
						// oui ->informer grand chef, le plat est a qui.
						informeTachePret(p);
						System.out
								.println("********************************done");
						i.remove();
					} else if (p.getEtat() == Etat_Plat.new_one) {
						// new tache ->informer l'apprendi.
						// si il y a un apprendi qui est libre,
						// informer et donner la tache
						synchronized (Specialiste.class) {
							Apprendi apprendiLibre = getApprendiLibre();
							if (apprendiLibre != null) {
								informeApprendis(p, apprendiLibre, p.getOwner());
							}
						}

					} else {
						// ingredient sont pas prets -> faire, rien, continue.
					}

				}
				if (hasIngredientsPret()) {
					System.out.println(this);
					// get numero de apprendi qui fini ses tacehs.
					int numeroAP = getNumeroAPFini();
					int numeroOwner = getPlatOwner(numeroAP);
					/* System.out.println("Owner:"+numeroOwner); */
					for (int i = 0; i < taches.size(); i++) {
						Plat p = taches.get(i);
						if (p.getOwner() == numeroOwner) {
							p.setEtat(Etat_Plat.ready_to_do);
						}
					}
				}
			}
			/*
			 * System.out.println("******************");
			 * System.out.println(this);
			 * System.out.println("******************");
			 */
		}
	}

	/**
	 * obtenir le possesseur du plat
	 * */
	private int getPlatOwner(int numeroAP) {
		// TODO Auto-generated method stub
		// knowref(SP0, tache(C1)=AP2)
		synchronized (this) {
			for (int i = 0; i < this.getEtat_mentaux().size(); i++) {
				Etat_Mental em = this.getEtat_mentaux().get(i);
				if (em.getFormule().contains("tache(C")
						&& em.getFormule().contains(")=AP" + numeroAP)) {
					int num = Integer.parseInt(em.getFormule().substring(7, 8));
					this.getEtat_mentaux().remove(i);
					return num;
				}
			}
		}
		return -1;
	}

	/**
	 * obtenir le numero d'apprenti qui fini ses taches.
	 * */
	private int getNumeroAPFini() {
		// TODO Auto-generated method stub
		// cherche
		// knowif(SP0, tache(AP2)=fini)
		synchronized (this) {
			for (int i = 0; i < this.getEtat_mentaux().size(); i++) {
				Etat_Mental em = this.getEtat_mentaux().get(i);
				if (em.getDescription().equalsIgnoreCase("knowref")
						&& em.getFormule().contains("fini")) {
					int num = Integer.parseInt(em.getFormule().substring(8, 9));
					this.getEtat_mentaux().remove(i);
					return num;
				}
			}
		}
		return -1;
	}

	/**
	 * Est-ce que tous ingredients sont pret?
	 * */
	private boolean hasIngredientsPret() {
		// TODO Auto-generated method stub
		for (int i = 0; i < this.getEtat_mentaux().size(); i++) {
			Etat_Mental em = this.getEtat_mentaux().get(i);
			if (em.getFormule().contains("tache(AP")
					&& em.getFormule().contains("fini")) {
				return true;
			}
		}
		return false;
	}

	/**
	 * obtenir les apprentis qui sont libres
	 * */
	private Apprendi getApprendiLibre() {
		// TODO Auto-generated method stub
		for (int i = 0; i < Apprendi.apprendis.size(); i++) {
			Apprendi a = Apprendi.apprendis.get(i);
			if (a.getEtat() == Etat_Serveur.free) {
				return a;
			}
		}
		return null;
	}

	/**
	 * genere les etat mentaux pour apprendis a cherche les ingredients
	 * */
	private void informeApprendis(Plat p, Apprendi a, int numeroClient) {
		// TODO Auto-generated method stub
		// modifier l'etat mental d'apprendi ->etat.busy;
		a.setEtat(Etat_Serveur.waiting);
		// Action:
		Swing.TAP[numeroClient] += ", partager(" + this.getId() + ","
				+ a.getId() + "," + p.getNom() + "_a_faire)";

		// ajouter
		// un tache au apprendi. -> knowref(AP0,donneTache(SP0))
		Etat_Mental e = new Etat_Mental();
		e.setAgent_X(a);
		e.setDescription("knowref");
		e.setFormule("donneTache(" + this.getId() + ")");
		a.addEtatMental(e);

		// ajouter
		// want(AP0,canFound(oeuf))
		for (int i = 0; i < Plat.plats.size(); i++) {
			Plat plat = Plat.plats.get(i);
			if (plat.getNom().equalsIgnoreCase(p.getNom())) {
				Vector<String> nomIngredients = plat.getIngredients();
				// ajouter les etat mentaux au apprendi
				for (int j = 0; j < nomIngredients.size(); j++) {
					Etat_Mental em = new Etat_Mental();
					em.setAgent_X(a);
					em.setDescription("want");
					em.setFormule("canFound(" + nomIngredients.get(j) + ")");
					a.addEtatMental(em);
				}
			}
		}
		// change
		// l'etat du plat: new_one -> not_ready
		p.setEtat(Etat_Plat.not_ready);

		// ajouter
		// knowref(SP0,tache(C0)=AP0)
		Etat_Mental em = new Etat_Mental();
		em.setAgent_X(this);
		em.setDescription("knowref");
		em.setFormule("tache(" + "C" + numeroClient + ")=" + a.getId());
		this.addEtatMental(em);
	}

	/**
	 * informer au chef de cuisine que le plat est pret.
	 * 
	 * */
	private void informeTachePret(Plat p) {
		// TODO Auto-generated method stub
		Chef c = Chef.grand_chef;
		// ajouter au les etat mentaux du chef
		// knowref(GC0,possede(C0,pret(nomPlat))=true)
		synchronized (Specialiste.class) {
			Etat_Mental em = new Etat_Mental();
			em.setAgent_X(c);
			em.setDescription("knowref");
			em.setFormule("possede(C" + p.getOwner() + ",pret("
					+ p.getType().toString() + "))=true");
			c.addEtatMental(em);
		}
		// change l'etat
		for (int i = 0; i < this.getEtat_mentaux().size(); i++) {
			Etat_Mental em = this.getEtat_mentaux().get(i);
			if (em.getDescription().equalsIgnoreCase("knowref")
					&& em.getFormule()
							.contains("pret(possede(C" + p.getOwner())
					&& em.getFormule().contains("false")
					&& em.getFormule().contains(p.getNom())) {
				em.setFormule(em.getFormule().replaceAll("false", "true"));
				System.out.println(p.getNom() + "*****************"
						+ em.getFormule());
			}
		}
		// Action:
		Swing.TAP[p.getOwner()] += ", informer(" + this.getId() + ","
				+ c.getId() + "," + p.getNom() + "_pret)";

	}

	/**
	 * transformer les taches aux les etat mentaux
	 * */
	private void analyserTache() {
		// TODO Auto-generated method stub
		// synchronized (this) {
		// Etat_Mental e = new Etat_Mental();
		// // cherche
		// // knowref(SP0,demande(C0)=nomPlat)
		// for (Iterator<Etat_Mental> i = this.getEtat_mentaux().iterator(); i
		// .hasNext();) {
		// Etat_Mental em = i.next();
		// String description = em.getDescription();
		// String formule = em.getFormule();
		//
		// if (description.equalsIgnoreCase("knowref")
		// && formule.contains("demande(C")) {
		// // retirer nom du plat
		// String nomPlat = formule.substring(12);
		// int owner = Integer.parseInt(formule.substring(9, 10));
		// for (Iterator<Plat> j = Plat.plats.iterator(); j.hasNext();) {
		// Plat p = j.next();
		// // obtenir le detail du plat
		// if (p.getNom().equalsIgnoreCase(nomPlat)
		// && p.getType() == this.getCapacite()) {
		// Plat plat = new Plat(p);
		// plat.setOwner(owner);
		// // ajouter au taches du specialiste.
		// taches.add(plat);
		// // ajouter
		// // knowref(SP0,pret(demande(C0,pizza))=false)
		//
		// e.setAgent_X(this);
		// e.setDescription("knowref");
		// e.setFormule("pret(possede(C" + plat.getOwner()
		// + "," + plat.getNom() + "))=false");
		// }
		// }
		// // supprimer
		// // knowref(SP0,demande(C0)=nomPlat)
		// i.remove();
		// }
		// }
		// this.addEtatMental(e);
		// }

		Etat_Mental e = new Etat_Mental();
		// cherche
		// knowref(SP0,demande(C0)=nomPlat)
		int numeroPlatASupprimer = -1;
		for (int i = 0; i < this.getEtat_mentaux().size(); i++) {
			Etat_Mental em = this.getEtat_mentaux().get(i);
			String description = em.getDescription();
			String formule = em.getFormule();

			if (description.equalsIgnoreCase("knowref")
					&& formule.contains("demande(C")) {
				// retirer nom du plat
				String nomPlat = formule.substring(12);
				int owner = Integer.parseInt(formule.substring(9, 10));
				for (int j = 0; j < Plat.plats.size(); j++) {
					Plat p = Plat.plats.get(j);
					// obtenir le detail du plat
					if (p.getNom().equalsIgnoreCase(nomPlat)
							&& p.getType() == this.getCapacite()) {
						Plat plat = new Plat(p);
						plat.setOwner(owner);
						// ajouter au taches du specialiste.
						taches.add(plat);
						// ajouter
						// knowref(SP0,pret(demande(C0,pizza))=false)

						e.setAgent_X(this);
						e.setDescription("knowref");
						e.setFormule("pret(possede(C" + plat.getOwner() + ","
								+ plat.getNom() + "))=false");
					}
				}
				// supprimer
				// knowref(SP0,demande(C0)=nomPlat)
				numeroPlatASupprimer = i;
				break;
			}
		}
		if (numeroPlatASupprimer != -1) {
			this.getEtat_mentaux().remove(numeroPlatASupprimer);
		}
		this.addEtatMental(e);
	}

	/**
	 * Est-ce que le specialiste a recu un tahce?
	 * */
	public boolean hasTacheArrive() {
		// cherche
		// knowref(SP0,demande(C0)=nomPlat)
		synchronized (this) {
			if (!this.getEtat_mentaux().isEmpty()) {
				for (int i = 0; i < this.getEtat_mentaux().size(); i++) {
					Etat_Mental em = this.getEtat_mentaux().get(i);
					String description = em.getDescription();
					String formule = em.getFormule();
					if (description.equalsIgnoreCase("knowref")
							&& formule.contains("demande(C")) {
						return true;
					}
				}
			}
			return false;
		}
	}
}
